/*
Creation date:	from 29/04/2003 to 01/04/2003

Autor:			Mountaniol Vsevolod <sebastian@vboxcomm.com>

File:			updater.c

Description:	Create updates for XLT / XR1 systems. 
                Also apply update on target machines.
*/
#include "updater.types.h"
#include "updater.h"
#include "updater.encode.h"
#include "updater.errors.h"
#include "updater.utils.h"
#include "updater.info.h"
#include "updater.version.h"

#include "updater.w.h"
#include "updater.w.system.h"
#include "updater.w.file.h"
#include "updater.w.string.h"
#include "updater.w.memory.h"



/* TODO!!! Rewrite! */

static INT FillFileHeader(ucore_t * ps_ucore, file_header_t * ps_fh, const file_list_t * ps_fl)
{
    ENTRY();
    if ( NULL == ps_ucore || NULL == ps_fh || NULL == ps_fl || NULL == ps_fl->file_name )
    {
        DD("Wrong argument\n");
        RETURN( - EARGUMENT );
    }

    if ( 0 != w_stat(ps_fl->file_name, &ps_fh->stat ) )
    {
        DD("Can't get stat of %s\n", ps_fl->file_name);
        RETURN( - ECANCELED );
    }


    w_strncpy(ps_fh->orig_path , ps_fl->file_name, FH_PATH_SIZE);

    if ( ps_fl->path_to_install )
    {
        w_strncpy(ps_fh->target_path, ps_fl->path_to_install, FH_PATH_SIZE);
    }
    else
    {
        w_strncpy(ps_fh->target_path, ps_fl->file_name, FH_PATH_SIZE);
    }

    ps_fh->compress_in_size = *ps_ucore->buffers.size_in;
    ps_fh->compress_out_size = *ps_ucore->buffers.size_out;
    DD("ps_fh->compress_in_size = %ld\n", ps_fh->compress_in_size);
    DD("ps_fh->compress_out_size = %ld\n", ps_fh->compress_out_size);
    w_memcpy(ps_fh->compressor, ps_fl->compressor, FL_COMPRESSOR_SIZE);
    w_memcpy(ps_fh->encriptor, ps_fl->encriptor, FL_ENCRIPTOR_SIZE);
    ps_fh->flags =  ps_fl->flags;


    /* XXX TODO the rest: compressors etc. */   

    RETURN(OK);
}



/*
    FUNCTION: CreatePackage
    IN: struct flist *
    OUT: int
    Get main structure of updater.
    Open output file.
    Read file by file from the list of files (ps_ucore->file_list)
    Compress, encript, and write to output file.
*/

static INT FillPackageHeader(ucore_t * ps_ucore, packet_header_t * ps_pheader)
{
    CHAR * pc_pv;
    ENTRY();
    pc_pv = w_memcpy(ps_pheader->magic, PACKET_MAGIC_WORD, PACKET_MAGIC_SIZE);

    if ( ps_pheader->magic != pc_pv )
    {
        RETURN( - ECANCELED );
    }

    pc_pv = w_memcpy(ps_pheader->description, ps_ucore->env.packet_description, PACKET_DESCRIPTION_SIZE);

    if ( pc_pv != ps_pheader->description )
    {
        RETURN( - ECANCELED );
    }

    pc_pv = w_memcpy(ps_pheader->name, ps_ucore->env.packet_name, PACKET_NAME_SIZE);

    if ( pc_pv != ps_pheader->name )
    {
        RETURN( - ECANCELED );
    }

    ps_pheader->flags = ps_ucore->env.package_flags;
    ps_pheader->major = ps_ucore->env.major;
    ps_pheader->minor = ps_ucore->env.minor;
    ps_pheader->version = UPDATER_VERSION;

    /*	TODO

    ps_pheader->control_sum;
    ps_pheader->reserved;
    */


    RETURN( OK );
}

INT PackSingleFile(ucore_t * ps_ucore, const file_list_t * ps_fl)
{
    file_header_t s_fh;
    long l_last_header; /* location of last header - see 3.3 below for explanation */
    INT i_rv;
    INT i_eof;
    long l_output_counter = 0; /* Count the output */


    ENTRY();
    /*	3.1  Open input file */
    ps_ucore->file_in = w_open(ps_fl->file_name, W_O_RDONLY);

    if ( NULL == ps_ucore->file_in )
    {
        PRINT("Can't open for reading: |%s|",ps_fl->file_name );
        RETURN( - EFILEOPEN );
    }

    DD("Opened: |%s|\n", ps_fl->file_name );

#if defined(USE_HOOKS)
    /*	3.2  Call the hook */
    /* When this hook is opened the file descriptor points to begin of the file */
    /* This hook dedicated for the file preprocessing and the encoder change. */

    if ( NULL != ps_ucore->hooks.hook_in_file_opened )
    {
        DD("Called a hook `in file opened`");
        ps_ucore->hooks.hook_in_file_opened( ps_ucore, OK );
    }
    else
    {
        DD("Hook hook_in_file_opened is empty\n");
    }
#endif

    /*	TODO */

    /*  3.3 Create and write the header */

    /* The header writing is bit tricky. I should be redesigned. */
    /* First I create the header and write it into the output file */
    /* Then I read the current input file, */
    /* compress and/or encrypt it and also write it into the output. */
    /* I count the sum size of output and when whole the file processed I jump */
    /* back, to the header location, and write the length  */
    /* of written file (enctypted and compressed) to the header. */

    /* Such way I write the header twice: */
    /* First - before ouput, to catch the header's room */
    /* Second time - after the file is processed, to update the fh.size field */
    /* ------------------------- */
    /* to count _processed_ file length _before_ processing. */

    /* Other way to resolve this problem it is to write the header */ 
    /* of the file _after_ the processed file */
    /* But then I have no ability to know the data length and I need to run */
    /* the result package byte by byte until I'l find a header. */


    if ( OK != FillFileHeader(ps_ucore, &s_fh, ps_fl) )
    {
        w_close(ps_ucore->file_in);
        RETURN( - ERR );
    }

    /* Read the current position */
	/* TODO: XXX: Remake */
    l_last_header = w_lseek(ps_ucore->file_out, 0, W_SEEK_CUR);

    i_rv = w_write(ps_ucore->file_out, (CHAR *) &s_fh,sizeof(file_header_t) );

    if ( i_rv < 1 )
    {
        w_close(ps_ucore->file_in);
        RETURN( - ERR );
    }

    /*	3.4	 Read buffer by buffer from the input file. */

    i_eof = 0;

    while ( 0 == i_eof )
    {
        ps_ucore->buffers.size_effective = w_read( ps_ucore->file_in,
                                                   (CHAR *) ps_ucore->buffers.buffer_in, 
                                                    DEFAULT_BUFF_BIG);

        /* Ok. Did it read? */
        if ( ps_ucore->buffers.size_effective <= 0 )
        {
            DD("Finished to read\n");
            i_eof = 1;
            continue;
        }
#if defined (USE_HOOKS)
        /*	3.4  Call the hook. */

        if ( ps_ucore->hooks.hook_buffer_in )
        {
            if ( OK != ps_ucore->hooks.hook_buffer_in(ps_ucore, OK) )
            {
                w_close(ps_ucore->file_in);
                RETURN( - ERR );
            }
        }

        /*	Encrypt buffer. */
        /*	3.5  Call the hook. */
        if ( ps_ucore->hooks.hook_encode )
        {
            if ( OK != ps_ucore->hooks.hook_encode( ps_ucore, OK ) )
            {
                /* Error : stop and exit! */
            }
        }

        /*	Compress buffer. */
        /*	3.6  Call the hook. */
        if ( ps_ucore->hooks.hook_compress )
        {
            if ( OK != ps_ucore->hooks.hook_compress(ps_ucore, OK) )
            {
                w_close(ps_ucore->file_in);
                RETURN(-EHOOK);
            }

        }

        /*	3.10 Call the hook hook_buffer_out. */
        if ( NULL != ps_ucore->hooks.hook_buffer_out )
        {
            if ( OK != ps_ucore->hooks.hook_buffer_out(ps_ucore, OK) )
            {
                w_close(ps_ucore->file_in);
                RETURN (- EHOOK);
            }
        }
#endif

        /*	3.9	 Write to the output file. */

        if ( ps_ucore->buffers.size_effective != w_write(
                            ps_ucore->file_out,
                            ps_ucore->buffers.buffer_in, 
                            ps_ucore->buffers.size_effective) )
        {
            w_close(ps_ucore->file_in);
            RETURN( - ERR ) ;
        }

        l_output_counter += ps_ucore->buffers.size_effective;
    }

    /* 3.12 Update the header */

    /* Update the size in header structure */
    s_fh.size = l_output_counter;

    /* Seek the structure: backward offset of written data + size of s_file_header */
    if ( 0 != w_lseek (ps_ucore->file_out, -1 * (l_output_counter + sizeof(file_header_t)),W_SEEK_CUR) )
    {
        w_close(ps_ucore->file_in);
        RETURN ( -ERR);
    }

    /* Write the header */
    if (  sizeof(file_header_t) != w_write(ps_ucore->file_out, (CHAR *) &s_fh,sizeof(file_header_t) ) )
    {
        w_close(ps_ucore->file_in);
        RETURN( - ERR );
    }

    /* Position to the end of stream */
    w_lseek (ps_ucore->file_out, 0, W_SEEK_END);

    /* Zero output counter */

    l_output_counter = 0;

    i_rv = w_close ( ps_ucore->file_in );
    if ( i_rv != 0 )
    {
        w_close(ps_ucore->file_in);
        PERROR("Can't close file: ");
        RETURN(- ERR);
    }

    w_close(ps_ucore->file_in);
    RETURN(OK);
}


INT CreatePackage (ucore_t * ps_ucore) 
{
    packet_header_t s_pheader;
    file_list_t * ps_file_list_copy;
    INT i_rv;
    ENTRY();

    /*	1. 	Test struct ucore_t. */
    if ( NULL == ps_ucore )
    {
        PRINT("Error: ps_ucore == NULL\n");
        RETURN( - EARGUMENT );
    }

    /* Thest the file list presence. If the list doesn't present then  just exit. */
    if ( NULL == ps_ucore->file_list )
    {
        PRINT("Error: ps_ucore->file_list == NULL\n");
        RETURN( - EARGUMENT );
    }

    /*	2. 	Open an output file and lock the field. */

    /* Test file name */

    if ( NULL == ps_ucore->env.output_file_name )
    {
        PRINT("Output file name is NULL. Exit.\n");
        RETURN( - EFILEOPEN );
    }

    /* Open the given file name - create the update package.  */
    ps_ucore->file_out = w_open(ps_ucore->env.output_file_name, W_O_RDWR );
    if ( NULL == ps_ucore->file_out )
    {
        PRINT("Can't open output file: |%s|\n", ps_ucore->env.output_file_name);
        w_perror("");
        RETURN( - EFILEOPEN );
    }

#if defined(USE_HOOKS)
    /* Call the "file open" hook */
    if ( NULL != ps_ucore->hooks.hook_out_file_opened )
    {
        ps_ucore->hooks.hook_out_file_opened( ps_ucore, OK );
    }
    else
    {
        DD("Hook hook_out_file_opened is empty\n");
    }
#endif

    /* Allocate buffers */

    i_rv = AllocateInOutBuffers(ps_ucore, DEFAULT_BUFF_BIG, DEFAULT_BUFF_BIG);

    if ( i_rv )
    {
        RETURN(i_rv);
    }

    /*	Create package header */

    i_rv = FillPackageHeader(ps_ucore, &s_pheader);
    if ( OK != i_rv )
    {
        PRINT("Can't fill packet header\n");
        RETURN(i_rv);
    }

    /* Write package header */

    i_rv = w_write(UPD_FOUT(ps_ucore), (CHAR *) &s_pheader, sizeof(packet_header_t));

    if ( i_rv <  sizeof(packet_header_t) )
    {
        DD("Error on writing packet header. Stoped.\n");
        /* XXX Error. Stop. */
    }


    /*	2.1  Call the hook. */
    /*	TODO */

    /*	3. 	 Read file by file. */
    ps_file_list_copy = ps_ucore->file_list;
    while ( NULL != ps_file_list_copy )
    {
        i_rv = PackSingleFile(ps_ucore, ps_file_list_copy);
        if ( OK != i_rv )
        {
            goto error_3;
        }
        ps_file_list_copy = ps_file_list_copy->next;
    } /* End while */

    /*	Now count control sum and write package header again */

    /*	4. Close output file */
    w_close (ps_ucore->file_out);

    /*	5. Return status and exit */
    RETURN( OK );

    error_3:
    w_free(ps_ucore->buffers.buffer_out);
    w_free(ps_ucore->buffers.buffer_in);

    w_close(ps_ucore->file_out);
    if ( w_unlink(ps_ucore->env.output_file_name) )
    {
        PERROR("Cannot delete output file: ");
    }
    RETURN( - EFILEOPEN );

}

#if(0)
/* 
    FUNCTION: 	__compress_file
    IN: 		file name, pc_f_install.
    OUT: 		status, where 0 - success, else - error.
    Get file name of 'source_file' . 
    Open the file, compress it into 'source_file.cmp'
    If pc_f_install not NULL it will be name + path of file on decompress.
*/
    #define FREE_BUFFS() do{w_free(pc_buff_little); w_free(pc_buff_big);w_free(ps_fh);} while(0)

static INT __compress_file(CHAR * pc_file_name_in, CHAR * pc_f_install, ULONG ul_flags)
{
    CHAR *pc_file_name_out;
    Bytef * pc_buff_little;
    Bytef * pc_buff_big;
    INT i_fd_in;
	INT i_fd_out;
	INT i_rv;
	INT i_rv_out;
    ULONG ul_not_compressed_data_size;
    ULONG ul_compressed_data_size;
    ULONG ul_size_passed = 0;
    struct file_header * ps_fh;

    /*	construct output file name */
    pc_file_name_out = ConstructName(pc_file_name_in, F_COMPRESS);

    if ( pc_file_name_out == NULL )
    {
        RETURN( - ECANCELED );
    }

    /*	allocate memory for file header */
    ps_fh = (struct file_header *) w_malloc(sizeof(struct file_header));

    if ( ps_fh == NULL )
    {
        PERROR("Low mem: ");
        RETURN( - ENOMEM );
    }

    /*	clean file header */
    w_memset (ps_fh, 0, sizeof(struct file_header));

    /*	read input file stat */ 
    i_rv = w_stat(pc_file_name_in, &ps_fh->stat);
    if ( i_rv )
    {
        PERROR("Can not stat file: ");
        w_free(ps_fh);
        RETURN( - ECANCELED );
    }

    /*	fill file header */
    ps_fh->major = 0;
    ps_fh->minor = 1;
    ps_fh->flags = ul_flags;

    if ( pc_f_install != NULL )
    {
        DD("pc_f_install:%s\n", pc_f_install);
        w_strcpy (ps_fh->path, pc_f_install);
    }
    else
    {
        w_strcpy (ps_fh->path, pc_file_name_in);
    }

    w_strcpy (ps_fh->description, "This is just test");

    /*	TODO count here CNTSUM and wrote to header */
    /* memcpy (ps_fh->singature, SINGATURE, FH_SINGATURE_SIZE); */

    /*	open input file */
    i_fd_in = open (pc_file_name_in, O_RDONLY);
    if ( i_fd_in < 0 )
    {
        PERROR("Cant open source: ");
        w_free(ps_fh);
        RETURN( - EIO );
    }

    /*	open output file */
    i_fd_out = open (pc_file_name_out, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRWXG |  S_IRGRP);
    if ( i_fd_out < 0 )
    {
        PERROR("Cant open dest: ");
        w_free(ps_fh);
        RETURN( - EIO );
    }

    /*	write file header */
    i_rv = write(i_fd_out, ps_fh, sizeof(struct file_header));
    if ( i_rv != sizeof(struct file_header) )
    {
        PERROR("Can't write file_header to header:");
        w_free(ps_fh);
        RETURN( - EIO );
    }

    /*	TODO - use here buff size from user */
    pc_buff_little  = w_malloc(DEFAULT_BUFF_SMALL);

    if ( NULL == pc_buff_little )
    {
        PERROR("Not enough memory");
        RETURN( -ENOMEM );
    }

    /* TODO - use here buffer size from user */
    pc_buff_big = w_malloc(DEFAULT_BUFF_BIG);

    if ( NULL == pc_buff_big )
    {
        PERROR("Not enough memory");
        w_free(ps_fh);
        RETURN( - ENOMEM );
    }


    /*	read input file, compress / decompress , and write into output file */
    do
    {
        /* 	TODO - use here buffer size from user */
        ul_not_compressed_data_size = read (i_fd_in, pc_buff_little, DEFAULT_BUFF_SMALL);
        /*	DD ("read: %i\n", i_rv);	*/

        /*	did it read something? */
        if ( ul_not_compressed_data_size > 0 )
        {

            /* 	TODO - use here buffer size from user */
            ul_compressed_data_size = DEFAULT_BUFF_BIG;

            /*	yes it did. Compress / decompress buffer */
            i_rv_out = compress2 (pc_buff_big, &ul_compressed_data_size, pc_buff_little, ul_not_compressed_data_size, 9);

            /*	check was there error or not */
            switch ( i_rv_out )
            {
            case Z_MEM_ERROR:
                PRINT("Compression memory error\n");
                FREE_BUFFS();
                RETURN( - ENOMEM );

            case Z_BUF_ERROR:
                PRINT("Output buffer too small\n");
                FREE_BUFFS();
                RETURN( - ENOMEM );

            default:
/*		  PRINT("out: %u\n", (unsigned int) ul_compressed_data_size);	*/
                ul_size_passed += ul_not_compressed_data_size; 
                PRINT("\r[%.10u / %.10u] - %s", (unsigned int) ul_size_passed, (unsigned int) ps_fh->stat.st_size,  ps_fh->path);
                break;
            }

            /*	no errors due compress. Write the buffer into output file */ 

            /*	1. write the len of compressed buff - I need it for decompress  */
            i_rv_out = write (i_fd_out, &ul_compressed_data_size, sizeof(ul_compressed_data_size));

            /* 	2. write the len of original not compressed buffer */
            i_rv_out = write (i_fd_out, &ul_not_compressed_data_size, sizeof(ul_not_compressed_data_size));

            /*	3. write down compressed date itself */
            i_rv_out = write (i_fd_out, pc_buff_big, ul_compressed_data_size);

            /*	wrote ok? */
            if ( i_rv_out != ul_compressed_data_size )
            {
                PRINT("Error writing compressed date!\n");
                FREE_BUFFS();
                RETURN( - EIO );
            }
        }
    } while ( ul_not_compressed_data_size > 0 );

    PRINT("\n");


    /*	close files */
    close (i_fd_out);
    close (i_fd_in);

    /*	free buffer */
    if ( NULL != pc_file_name_out )
    {
        w_free(pc_file_name_out);
    }

    /*	exit */
    FREE_BUFFS();
/*  TFREE(ps_fh); */
    RETURN( 0 );
}
    #undef FREE_BUFFS


INT concat_files (CHAR * pc_file_name_out, struct flist * ps_fl)
{
    struct flist * ps_fl_copy;
    file_header_t s_file_header;
    CHAR * pc_local_buf = NULL;
    INT i_fd_in;
	INT i_fd_out;
	INT i_rv;
    struct stat s_st;
    CHAR * pc_file_name_in = NULL;
    packet_header_t s_pheader;



    if ( pc_file_name_out == NULL || ps_fl == NULL )
    {
        RETURN( - EINVAL );
    }

    /*	open output file */
    i_fd_out = open(pc_file_name_out, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRWXG | S_IRGRP);
    if ( i_fd_out < 0 )
    {
        PERROR("Can't open concat file");
        RETURN( - EIO );
    }

    /* Fill structures with 0 */
    w_memset(&s_file_header, 0, sizeof(file_header_t));
    w_memset(&s_pheader, 0, sizeof(packet_header_t));

    s_pheader.version = UPDATER_VERSION;

    w_strcpy (s_pheader.name, "Name");
    w_strcpy (s_pheader.description, "Update");
    w_strncpy(s_pheader.magic, PACKET_MAGIC_WORD, PACKET_MAGIC_SIZE);


    /* 	TODO - count here CNTSUM and write to header! */

    if ( FindFile(ps_fl,PREINSTALL_SCRIPT_NAME) == 0 )
    {
        PRINT("Set flag UPD_HAS_PREINSTALL\n");
        SET_FLAG(s_pheader.flags, UPD_HAS_PREINSTALL);
    }

    if ( FindFile(ps_fl,POSTINSTALL_SCRIPT_NAME) == 0 )
    {
        PRINT("Set flag UPD_HAS_POSTINSTALL: %d\n",UPD_HAS_POSTINSTALL);
        SET_FLAG(s_pheader.flags, UPD_HAS_POSTINSTALL);
    }

    i_rv = write (i_fd_out, &s_pheader, sizeof(packet_header_t));

    if ( i_rv != sizeof(struct s_file_header) )
    {
        PERROR ("Can't write header");
        RETURN( - EIO );
    }

    /* 	TODO - use here buffer size from user */

    pc_local_buf = w_malloc (DEFAULT_BUFF_BIG);
    if ( NULL == pc_local_buf )
    {
        PERROR("Not enough mem");
        RETURN( - ENOMEM );
    }

    ps_fl_copy = ps_fl;
    while ( ps_fl_copy != NULL )
    {
        /*	construct name of compressed file from the name of regular file */
        TFREE(pc_file_name_in);
        pc_file_name_in = ConstructName(ps_fl_copy->file_name, F_COMPRESS);

        /*	try stat() input file - anyway, I need size of the file */
        i_rv = w_stat(pc_file_name_in, &s_st);

        if ( i_rv < 0 )
        {
            PERROR("Can't stat file");
            w_free(ps_fh);
            RETURN( - EIO );
        }


        /*	open input file */
        i_fd_in = open(pc_file_name_in,O_RDONLY);
        if ( i_fd_in < 0 )
        {
            PERROR("Can't open compressed input file");
            w_free(ps_fh);
            RETURN( - EIO );
        }

        /*	write len of file */
        i_rv = write(i_fd_out, &s_st.st_size, sizeof(s_st.st_size));
        if ( i_rv != sizeof(s_st.st_size) )
        {
            PERROR("Can't write to concat file");
            w_free(ps_fh);
            RETURN( - EIO );
        }

        /* write input file to output */

        do
        {

            /*	read from input file */
            /* 	TODO - use here buffer size from user */
            i_rv = read (i_fd_in, pc_local_buf, DEFAULT_BUFF_BIG);

            if ( i_rv > 0 )
            {
                INT i_rv2;
                /*	write to concat file */
                i_rv2 = write(i_fd_out,pc_local_buf,i_rv);

                /*	check if wrote ok. */
                if ( i_rv2 != i_rv )
                {
                    PERROR("Couldn'r write buffer into concat file");
                    w_free(pc_local_buf);
                    w_free(ps_fh);
                    RETURN( - EIO );
                }

            }
        } while ( i_rv > 0 );

        close (i_fd_in);
        unlink(pc_file_name_in);
        ps_fl_copy = ps_fl_copy->next;

    }
    w_free(pc_local_buf);
    w_free(pc_file_name_in);
    w_free(ps_fh);
    RETURN( 0 ); 
}

INT FindAndExtractFile(CHAR * pc_file_name_in, CHAR * pc_file_name_out)
{
    if ( pc_file_name_in == NULL || pc_file_name_out == NULL )
    {
        RETURN( - EINVAL );
    }

    RETURN( 0 );
}

#endif

/*
 */

INT WriteDescriptionAndName (CHAR * pc_file_name, CHAR * description, CHAR * name)
{
    FD_T * ps_fd;
    INT i_rv;
    packet_header_t * ps_packet_header;
	
    if ( NULL == pc_file_name )
    {
        PRINT("Wrong file name\n");
        RETURN( - EINVAL );
    }

    /*	1. Open the file */
    ps_fd = w_open(pc_file_name, W_O_RDWR);
    if ( w_filestatus( ps_fd ) < 0 )
    {
        PERROR("Can't open file:");
        RETURN( - EIO );
    }

    /* Allocate memory for the header */
    /* TODO - it must be allowed also without dinamic allocation - for embedded systems */
    ps_packet_header = (packet_header_t *) w_malloc( sizeof ( packet_header_t) );


    /*	2. Read header of file to be updated */
    i_rv = w_read (ps_fd, (CHAR *) ps_packet_header, sizeof(packet_header_t));
    if ( i_rv != sizeof(packet_header_t) )
    {
        PERROR("Can't read packet header:");
        w_close(ps_fd);
        /*	TODO - if not EMBEDDED ! */
        w_free(ps_packet_header);
        RETURN( - EIO );
    }

    /*	validate magic word */

    if ( TEST_MAGIC(ps_packet_header->magic) != 0 )
    {
        PRINT("Magic worg is wrong\n");
        w_close(ps_fd);
        /*	TODO - if not EMBEDDED ! */
        w_free(ps_packet_header);
        RETURN( - ECANCELED );
    }

    /*	if description has given then copy it to header. */
    if ( description != NULL )
    {
        w_strncpy (ps_packet_header->description, description, PACKET_DESCRIPTION_SIZE);
    }

    /*	if name has given then copy it to header */
    if ( name != NULL )
    {
        w_strncpy (ps_packet_header->name, name, PACKET_NAME_SIZE);
    }

    i_rv = w_lseek (ps_fd, 0, W_SEEK_SET);
    if ( i_rv < 0 )
    {
        PERROR("Can't seek begin:");
        w_close(ps_fd);
        /* TODO - if not embedded ! */
        w_free(ps_packet_header);
        RETURN( - EIO );
    }

    i_rv = w_write(ps_fd, (CHAR *) ps_packet_header, sizeof(packet_header_t));
    if ( i_rv != sizeof(packet_header_t) )
    {
        PERROR("Package header couldn't be wrote back:");
        w_close(ps_fd);
        /* TODO - if not EMBEDDED !*/
        w_free(ps_packet_header);
        RETURN( - EIO );
    }
    w_close (ps_fd);
    /*	TODO - if not embedded ! */
    w_free(ps_packet_header);
    RETURN( 0 );
}



/*
    FUNCTION: 	FindAndExtractFile
    IN:			CHAR * pc_file_name_in, CHAR * pc_file_name_out
    OUT:		int
*/


